package org.notabug.lifeuser.moviedb;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;

import android.database.sqlite.SQLiteDatabase;

import android.os.Bundle;
import android.os.AsyncTask;

import android.support.design.widget.NavigationView;

import android.view.View;
import android.database.SQLException;
import android.database.Cursor;

import android.widget.AdapterView;
import android.widget.ListView;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import java.util.ArrayList;
import java.util.HashMap;

/*
* This class provides an overview of the movies/series saved in the database.
* This class contains a listview that presents all the movies/series.
*/
public class ListActivity extends BaseActivity implements
		NavigationView.OnNavigationItemSelectedListener {
	public Context context;

	private MovieBaseAdapter movieAdapter;
	private MovieBaseAdapter searchMovieAdapter;
	private ArrayList<JSONObject> movieArrayList;
	private ArrayList<JSONObject> searchMovieArrayList;
	private HashMap<String, String> movieGenreList;
	private ListView listView;
	private boolean searchView;

	private SQLiteDatabase database;
	private MovieDatabaseHelper databaseHelper;
	private int watchedValue;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_list);
		setNavigationDrawer();

		databaseHelper = new MovieDatabaseHelper(getApplicationContext());

		// Get all entries from the database,
		// put them in JSONObjects and send them to the MovieBaseAdapter.
		movieArrayList = new ArrayList<JSONObject>();

		// Check if the user requests the watch or watched list.
		try {
			watchedValue = getIntent().getExtras().getInt("watched");
		} catch(NullPointerException npe) {
			watchedValue = 1;
			npe.printStackTrace();
		}

		if(watchedValue == 1) {
			setTitle(getString(R.string.title_activity_list_watched));
		} else {
			setTitle(getString(R.string.title_activity_list_watch));
		}

		// Create the listView
		listView = (ListView) findViewById(R.id.listView);

		movieGenreList = new HashMap<String, String>();
		movieAdapter = new MovieBaseAdapter(getMoviesFromDatabase(null), movieGenreList, getApplicationContext());
		listView.setAdapter(movieAdapter);

		// Load the genres
		new GenreList().execute("tv");

		// Send user (and movieObject) to DetailActivity.
		listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view, 
					int position, long id) {
				Intent intent = new Intent(getApplicationContext(), DetailActivity.class);

				JSONObject movieObject;
				if(searchView) {
					movieObject = (JSONObject) searchMovieAdapter.getItem(position);
				} else {
					movieObject = (JSONObject) movieAdapter.getItem(position);
				}

				// Extra's can't just be any object so
				// JSONObject needs to be converted to a string.
				intent.putExtra("movieObject", movieObject.toString());
				
				// Check if it is a movie or a series.
				try {
					Cursor cursor = database.rawQuery("SELECT * FROM " + 
							databaseHelper.TABLE_MOVIES + " WHERE " +
							databaseHelper.COLUMN_MOVIES_ID + "=" + 
							movieObject.get("id") + " AND " + 
							databaseHelper.COLUMN_MOVIE + "=" + "1 LIMIT 1", null);

					if(cursor.getCount() > 0) {
						intent.putExtra("isMovie", true);
					} else {
						intent.putExtra("isMovie", false);
					}
				} catch(JSONException e) {
					e.printStackTrace();
				}


				startActivity(intent);
			}
		});
	}

	private ArrayList<JSONObject> getMoviesFromDatabase(String searchQuery) {
		ArrayList<JSONObject> dbMoviesArrayList = new ArrayList<JSONObject>();

		open();
		databaseHelper.onCreate(database);

		Cursor cursor;
		// Search for movies that fulfill the searchQuery and fit in the list.
		if(searchQuery != null) {
			cursor = database.rawQuery("SELECT * FROM " + databaseHelper.TABLE_MOVIES
			+ " WHERE " + databaseHelper.COLUMN_TITLE + " LIKE '%" + searchQuery + 
			"%' AND " + databaseHelper.COLUMN_WATCHED + "=" + watchedValue, null);
		} else {
			cursor = database.rawQuery("SELECT * FROM " + databaseHelper.TABLE_MOVIES 
			+ " WHERE " + databaseHelper.COLUMN_WATCHED + "=" + watchedValue, null);
		}

		cursor.moveToFirst();
		// Convert the cursor object to a JSONObject (that way code can be reused).
		while(!cursor.isAfterLast()) {
			JSONObject movieObject = new JSONObject();
			try {
				// Use the MovieDatabase naming standards.
				movieObject.put("id", cursor.getInt(
						cursor.getColumnIndex(
						MovieDatabaseHelper.COLUMN_MOVIES_ID)));
				if(watchedValue == 1) {
					movieObject.put("vote_average", cursor.getInt(
							cursor.getColumnIndex(
							MovieDatabaseHelper.COLUMN_PERSONAL_RATING)));
				} else {
					movieObject.put("vote_average", cursor.getInt(
							cursor.getColumnIndex(
							MovieDatabaseHelper.COLUMN_RATING)));
				}
				movieObject.put("backdrop_path", cursor.getString(
						cursor.getColumnIndex(
						MovieDatabaseHelper.COLUMN_IMAGE)));
				movieObject.put("poster_path", cursor.getString(
						cursor.getColumnIndex(
						MovieDatabaseHelper.COLUMN_ICON)));
				movieObject.put("title", cursor.getString(
						cursor.getColumnIndex(
						MovieDatabaseHelper.COLUMN_TITLE)));
				movieObject.put("overview", cursor.getString(
						cursor.getColumnIndex(
						MovieDatabaseHelper.COLUMN_SUMMARY)));
				movieObject.put("genre_ids", cursor.getString(
						cursor.getColumnIndex(
						MovieDatabaseHelper.COLUMN_GENRES_IDS)));
			} catch(JSONException e) {
				e.printStackTrace();
			}
			// Add the JSONObject to the list and move on to the next.
			dbMoviesArrayList.add(movieObject);
			cursor.moveToNext();
		}
		cursor.close();

		return dbMoviesArrayList;
	}

	private void open() throws SQLException {
		database = databaseHelper.getWritableDatabase();
	}

	private void close() {
		databaseHelper.close();
	}

	@Override
	public void doSearch() {
		// Get the query
		String searchQuery = editSearch.getText().toString();

		// Create movieBaseAdapter and load the search results
		if(!searchQuery.equals("")) {
			searchMovieArrayList = getMoviesFromDatabase(searchQuery);
			searchMovieAdapter = new MovieBaseAdapter(searchMovieArrayList,
					movieGenreList, getApplicationContext());
			listView.setAdapter(searchMovieAdapter);
		}
	}

	@Override
	public void searchCancelled() {
		// Replace the current (search) list with the movieList.
		searchView = false;
		listView.setAdapter(movieAdapter);
	}

	// Load the genres
	private class GenreList extends AsyncTask<String, Void, String> {

		private final String API_KEY = ConfigHelper.getConfigValue(getApplicationContext(), "api_key");
		
		protected String doInBackground(String... params) {
			String genreType = params[0];

			String line;
			StringBuilder stringBuilder = new StringBuilder();

			// Load the genre webpage.
			try {
				URL url = new URL("https://api.themoviedb.org/3/genre/"
						+ genreType + "/list?api_key=" + 
						API_KEY + getLanguageParameter());

				URLConnection urlConnection = url.openConnection();
				try {
					BufferedReader bufferedReader = new BufferedReader(
							new InputStreamReader(
							urlConnection.getInputStream()));

					// Create one long string of the webpage.
					while((line = bufferedReader.readLine()) != null) {
						stringBuilder.append(line).append("\n");
					}

					// Close connection and return the data from the webpage.
					bufferedReader.close();
					return stringBuilder.toString();
				} catch(IOException ioe) {
					ioe.printStackTrace();
				}
			} catch(MalformedURLException mue) {
				mue.printStackTrace();
			} catch(IOException ioe) {
				ioe.printStackTrace();
			}

			// Loading the dataset failed, return null.
			return null;
		}

		protected void onPostExecute(String response) {
			// Keep the user at the same position in the list.
			int position;
			try {
				position = listView.getFirstVisiblePosition();
			} catch(NullPointerException npe) {
				position = 0;
			}

			// Save GenreList to sharedPreferences, this way it can be used anywhere.
			SharedPreferences sharedPreferences = getApplicationContext()
					.getSharedPreferences("GenreList", Context.MODE_PRIVATE);
			SharedPreferences.Editor prefsEditor = 
					sharedPreferences.edit();

			// Convert the JSON data from the webpage to JSONObjects in an arraylist.
			try {	
				JSONObject reader = new JSONObject(response);
				JSONArray genreArray = reader.getJSONArray("genres");
				for(int i = 0; genreArray.getJSONObject(i) != null; i++) {
					JSONObject websiteData = genreArray.getJSONObject(i);
					movieGenreList.put(websiteData.getString("id"),
							websiteData.getString("name"));

				// Temporary fix until I find a way to handle this efficiently.
				prefsEditor.putString(websiteData.getString("id"),
						websiteData.getString("name"));
				prefsEditor.commit();
				}

				movieAdapter.notifyDataSetChanged();
			} catch(JSONException je) {
				je.printStackTrace();
			}
		}
	}
}
